/**
 * ThreadPoolManager.java
 * Created at 2016年11月1日
 * Created by Jackie Liu
 * Copyright (C) 2016 Jackie Liu, All rights reserved.
 */
package com.yunfeisoft.common.thread;

import org.springframework.beans.factory.InitializingBean;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p>ClassName: ThreadPoolManager</p>
 * <p>Description: 线程池管理</p>
 * <p>Author: Jackie Liu</p>
 * <p>Date: 2016年11月1日</p>
 */
public class ThreadPoolManager implements InitializingBean {

    //线程池中维护的线程最小数量
    private int corePoolSize = 2;
    //线程池中维护的线程最大数量
    private int maxPoolSize = 20;
    //线程池中维护的线程所允许的空闲时间
    private int keepAliveTime = 5;
    //队列容量
    private int queueCapacity = Integer.MAX_VALUE;
    //线程池管理类
    private ThreadPoolExecutor threadPool;

    public ThreadPoolManager() {
    }

    /**
     * <p>Description: 执行任务</p>
     *
     * @param task 子任务
     */
    public void executeTask(Runnable task) {
        threadPool.execute(task);
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    public int getKeepAliveTime() {
        return keepAliveTime;
    }

    public void setKeepAliveTime(int keepAliveTime) {
        this.keepAliveTime = keepAliveTime;
    }

    public void setCorePoolSize(int corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    public int getQueueCapacity() {
        return queueCapacity;
    }

    public void setQueueCapacity(int queueCapacity) {
        this.queueCapacity = queueCapacity;
    }

    /* (non-Javadoc)
     * <p>Title: afterPropertiesSet</p>
     * <p>Description: </p>
     * @throws Exception
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public void afterPropertiesSet() throws Exception {
        start();
    }

    public void start() {
        threadPool = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque(queueCapacity));
    }

    public void startSafe() {
        shutdown();
        start();
    }

    public void shutdown() {
        if (threadPool != null && !threadPool.isShutdown()) {
            threadPool.shutdown();
        }
    }

    public void shutdownNow() {
        if (threadPool != null && !threadPool.isShutdown()) {
            threadPool.shutdownNow();
        }
    }

    /**
     * 获取线程池监控参数
     *
     * @return
     */
    public Map<String, Object> getMonitor() {
        Map<String, Object> monitorMap = new HashMap<>();
        if (threadPool == null) {
            monitorMap.put("poolSize", 0);//初始线程数
            monitorMap.put("corePoolSize", 0);//核心线程数
            monitorMap.put("activeCount", 0);//正在执行的任务数量
            monitorMap.put("completedTaskCount", 0);//已完成任务数量
            monitorMap.put("taskCount", 0);//任务总数
            monitorMap.put("queueSize", 0);//队列里缓存的任务数量
            monitorMap.put("largestPoolSize", 0);//池中存在的最大线程数
            monitorMap.put("maximumPoolSize", 0);//最大允许的线程数
            monitorMap.put("keepAliveTime", 0);//线程空闲时间,单位秒
            monitorMap.put("isShutdown", true);//线程池是否关闭
            monitorMap.put("isTerminated", true);//线程池是否终止
        } else {
            monitorMap.put("poolSize", threadPool.getPoolSize());//初始线程数
            monitorMap.put("corePoolSize", threadPool.getCorePoolSize());//核心线程数
            monitorMap.put("activeCount", threadPool.getActiveCount());//正在执行的任务数量
            monitorMap.put("completedTaskCount", threadPool.getCompletedTaskCount());//已完成任务数量
            monitorMap.put("taskCount", threadPool.getTaskCount());//任务总数
            monitorMap.put("queueSize", threadPool.getQueue().size());//队列里缓存的任务数量
            monitorMap.put("largestPoolSize", threadPool.getLargestPoolSize());//池中存在的最大线程数
            monitorMap.put("maximumPoolSize", threadPool.getMaximumPoolSize());//最大允许的线程数
            monitorMap.put("keepAliveTime", threadPool.getKeepAliveTime(TimeUnit.SECONDS));//线程空闲时间,单位秒
            monitorMap.put("isShutdown", threadPool.isShutdown());//线程池是否关闭
            monitorMap.put("isTerminated", threadPool.isTerminated());//线程池是否终止
        }
        return monitorMap;
    }

    /**
     * 初始线程数
     *
     * @return
     */
    public int getPoolSize() {
        return threadPool.getPoolSize();
    }

    /**
     * 正在执行的任务数量
     *
     * @return
     */
    public int getActiveCount() {
        return threadPool.getActiveCount();
    }

    /**
     * 初始线程数
     *
     * @return
     */
    public long getCompletedTaskCount() {
        return threadPool.getCompletedTaskCount();
    }

    /**
     * 任务总数
     *
     * @return
     */
    public long getTaskCount() {
        return threadPool.getTaskCount();
    }

    /**
     * 队列里缓存的任务数量
     *
     * @return
     */
    public int getQueueSize() {
        return threadPool.getQueue().size();
    }

    /**
     * 池中存在的最大线程数
     *
     * @return
     */
    public int getLargestPoolSize() {
        return threadPool.getLargestPoolSize();
    }

    /**
     * 最大允许的线程数
     *
     * @return
     */
    public int getMaximumPoolSize() {
        return threadPool.getMaximumPoolSize();
    }

    /**
     * 线程空闲时间,单位秒
     *
     * @return
     */
    public long getKeepAliveTime2() {
        return threadPool.getKeepAliveTime(TimeUnit.SECONDS);
    }

    /**
     * 线程池是否关闭
     *
     * @return
     */
    public boolean isShutdown() {
        return threadPool.isShutdown();
    }

    /**
     * 线程池是否终止
     *
     * @return
     */
    public boolean isTerminated() {
        return threadPool.isTerminated();
    }
}
